<template>
	<ScrollArea
		ref="scrollAreaRef"
		v-slot="{containerSize,position}"
	>
		<VirtualScroll
			ref="virtualScrollRef"
			v-slot="slotScope"
			:data="data"
			:data-map="dataMap"
			:direction="direction"
			:min-size="minSize"
			:preload="preload"
			:scroll-offset="position[infos[direction].scrollProp]"
			:view-size="containerSize[infos[direction].sizeProp]"
		><slot v-bind="slotScope"/></VirtualScroll>
	</ScrollArea>
</template>

<script setup lang="ts">
import type {
	FieldGetter,
	MovePosition,
} from '../../../type';
import type {VirtualScrollItemScope} from '../VirtualScroll/type';
import {
	shallowRef,
} from 'vue';
import ScrollArea from '../ScrollArea/ScrollArea.vue';
import VirtualScroll from '../VirtualScroll/VirtualScroll.vue';
/**
 * 虚拟滚动组件(含滚动条)
 * @author 唐国雄
 * @date 2022/9/19
 * 属性----------------------
 * :data			列表数据
 * :data-map		映射数据
 * :direction		滚动方向
 * :min-size		最小尺寸
 * :preload			预加载数量
 * 插槽----------------------
 * #default			必须为组件且加key(否则可能有性能问题)
 * 方法----------------------
 * scrollTo(index,pos?,duration?)	滚动到指定位置
 */
if(typeof cache==='function'){
	cache=cache();
}
const {infos}=cache;

const props=withDefaults(defineProps<{
	data:Array<any>;
	dataMap?:FieldGetter<VirtualScrollItemScope,VirtualScrollItemScope>;
	direction?:Axis;
	minSize?:number;
	preload?:number;
}>(),{
	direction:'y',
});
const scrollAreaRef=shallowRef(null);
const virtualScrollRef=shallowRef(null);
//region 导出的内容
defineExpose({
	scrollTo(index:number,pos:MovePosition='nearest',duration?:number):Promise<void>{
		const {direction}=props;
		const scrollArea=scrollAreaRef.value;
		const virtualScroll=virtualScrollRef.value;
		if(pos==='nearest'){
			const {offset,itemSize}=virtualScroll.getInfo(index,'start');
			const {containerSize,position}=scrollArea.getInfo();
			const curScrollOffset=position[infos[direction].scrollProp];
			const viewSize=containerSize[infos[direction].sizeProp];
			if(offset<curScrollOffset){
				return scrollArea.setScrollPosition(direction,offset,duration);
			}else if(offset+itemSize>curScrollOffset+viewSize){
				return scrollArea.setScrollPosition(direction,offset-(viewSize-itemSize),duration);
			}
			return Promise.resolve();
		}
		return scrollArea.setScrollPosition(
			direction,
			virtualScroll.getInfo(index,pos).offset,
			duration,
		);
	},
});
//endregion
</script>

<script lang="ts">
import type {Axis} from '../../../type';
//region 类型声明
type Info={
	scrollProp:'x'|'y';
	sizeProp:'width'|'height';
};
interface Cache{
	infos:{
		// eslint-disable-next-line no-unused-vars
		[key in Axis]:Info;
	};
}
//endregion
//region 全局缓存
let cache:Cache|(() => Cache)=function(){
	return {
		infos:{
			x:{
				scrollProp:'x',
				sizeProp:'width',
			},
			y:{
				scrollProp:'y',
				sizeProp:'height',
			},
		},
	};
};
//endregion
export default {};
</script>